#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
客户服务管理系统 - Customer Service Management System

功能包括：
- 客户信息360度视图
- 服务工单管理系统
- 客户满意度调查
- 服务质量分析报告
"""

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
import json
import logging
from dataclasses import dataclass, asdict
from enum import Enum
import uuid
from collections import defaultdict

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class TicketStatus(Enum):
    """工单状态枚举"""
    OPEN = "open"              # 已开启
    IN_PROGRESS = "in_progress" # 处理中
    PENDING = "pending"        # 等待中
    RESOLVED = "resolved"      # 已解决
    CLOSED = "closed"          # 已关闭
    CANCELLED = "cancelled"    # 已取消

class TicketPriority(Enum):
    """工单优先级枚举"""
    LOW = "low"        # 低
    MEDIUM = "medium"  # 中
    HIGH = "high"      # 高
    URGENT = "urgent"  # 紧急

class TicketCategory(Enum):
    """工单类别枚举"""
    ORDER_INQUIRY = "order_inquiry"      # 订单查询
    DELIVERY_ISSUE = "delivery_issue"    # 配送问题
    PRODUCT_COMPLAINT = "product_complaint" # 产品投诉
    REFUND_REQUEST = "refund_request"    # 退款申请
    TECHNICAL_SUPPORT = "technical_support" # 技术支持
    GENERAL_INQUIRY = "general_inquiry"  # 一般咨询

class CustomerTier(Enum):
    """客户等级枚举"""
    BRONZE = "bronze"  # 铜牌
    SILVER = "silver"  # 银牌
    GOLD = "gold"      # 金牌
    PLATINUM = "platinum" # 白金
    DIAMOND = "diamond"   # 钻石

@dataclass
class Customer:
    """客户信息"""
    customer_id: str
    name: str
    email: str
    phone: str
    address: str
    registration_date: datetime
    tier: str = CustomerTier.BRONZE.value
    total_orders: int = 0
    total_spent: float = 0.0
    last_order_date: Optional[datetime] = None
    preferred_contact_method: str = "email"
    notes: str = ""
    is_active: bool = True

@dataclass
class ServiceTicket:
    """服务工单"""
    ticket_id: str
    customer_id: str
    category: str
    priority: str
    subject: str
    description: str
    status: str = TicketStatus.OPEN.value
    assigned_agent: str = ""
    created_date: datetime = None
    updated_date: datetime = None
    resolved_date: Optional[datetime] = None
    resolution: str = ""
    customer_satisfaction: Optional[int] = None  # 1-5分
    tags: List[str] = None
    
    def __post_init__(self):
        if self.created_date is None:
            self.created_date = datetime.now()
        if self.updated_date is None:
            self.updated_date = datetime.now()
        if self.tags is None:
            self.tags = []

@dataclass
class SatisfactionSurvey:
    """满意度调查"""
    survey_id: str
    customer_id: str
    ticket_id: str
    overall_satisfaction: int  # 1-5分
    response_time_rating: int  # 1-5分
    solution_quality_rating: int  # 1-5分
    agent_courtesy_rating: int  # 1-5分
    comments: str = ""
    survey_date: datetime = None
    
    def __post_init__(self):
        if self.survey_date is None:
            self.survey_date = datetime.now()

@dataclass
class ServiceAgent:
    """客服代表"""
    agent_id: str
    name: str
    email: str
    department: str
    skills: List[str]
    max_concurrent_tickets: int = 10
    current_tickets: int = 0
    total_resolved_tickets: int = 0
    average_resolution_time: float = 0.0  # 小时
    customer_satisfaction_score: float = 0.0
    is_available: bool = True

class CustomerServiceManager:
    """客户服务管理系统核心类"""
    
    def __init__(self):
        self.customers: Dict[str, Customer] = {}
        self.tickets: Dict[str, ServiceTicket] = {}
        self.surveys: Dict[str, SatisfactionSurvey] = {}
        self.agents: Dict[str, ServiceAgent] = {}
        self.ticket_history: Dict[str, List[Dict]] = {}  # 工单历史记录
        
    def register_customer(self, customer: Customer) -> bool:
        """注册客户"""
        try:
            self.customers[customer.customer_id] = customer
            logger.info(f"客户 {customer.name} 注册成功")
            return True
        except Exception as e:
            logger.error(f"客户注册失败: {e}")
            return False
    
    def update_customer_info(self, customer_id: str, updates: Dict) -> bool:
        """更新客户信息"""
        if customer_id not in self.customers:
            return False
        
        try:
            customer = self.customers[customer_id]
            for key, value in updates.items():
                if hasattr(customer, key):
                    setattr(customer, key, value)
            
            logger.info(f"客户 {customer_id} 信息更新成功")
            return True
        except Exception as e:
            logger.error(f"更新客户信息失败: {e}")
            return False
    
    def get_customer_360_view(self, customer_id: str) -> Optional[Dict]:
        """获取客户360度视图"""
        if customer_id not in self.customers:
            return None
        
        customer = self.customers[customer_id]
        
        # 获取客户的所有工单
        customer_tickets = [ticket for ticket in self.tickets.values() 
                          if ticket.customer_id == customer_id]
        
        # 统计工单信息
        ticket_stats = {
            'total_tickets': len(customer_tickets),
            'open_tickets': len([t for t in customer_tickets if t.status == TicketStatus.OPEN.value]),
            'resolved_tickets': len([t for t in customer_tickets if t.status == TicketStatus.RESOLVED.value]),
            'average_resolution_time': 0
        }
        
        # 计算平均解决时间
        resolved_tickets = [t for t in customer_tickets 
                          if t.status == TicketStatus.RESOLVED.value and t.resolved_date]
        if resolved_tickets:
            total_resolution_time = sum(
                (t.resolved_date - t.created_date).total_seconds() / 3600 
                for t in resolved_tickets
            )
            ticket_stats['average_resolution_time'] = round(
                total_resolution_time / len(resolved_tickets), 2
            )
        
        # 获取满意度调查
        customer_surveys = [survey for survey in self.surveys.values() 
                          if survey.customer_id == customer_id]
        
        satisfaction_stats = {
            'total_surveys': len(customer_surveys),
            'average_satisfaction': 0
        }
        
        if customer_surveys:
            avg_satisfaction = sum(s.overall_satisfaction for s in customer_surveys) / len(customer_surveys)
            satisfaction_stats['average_satisfaction'] = round(avg_satisfaction, 2)
        
        # 最近的交互记录
        recent_tickets = sorted(customer_tickets, key=lambda x: x.created_date, reverse=True)[:5]
        
        return {
            'customer_info': asdict(customer),
            'ticket_statistics': ticket_stats,
            'satisfaction_statistics': satisfaction_stats,
            'recent_tickets': [{
                'ticket_id': t.ticket_id,
                'subject': t.subject,
                'status': t.status,
                'created_date': t.created_date.isoformat(),
                'category': t.category
            } for t in recent_tickets],
            'customer_tier': customer.tier,
            'loyalty_metrics': {
                'total_orders': customer.total_orders,
                'total_spent': customer.total_spent,
                'customer_lifetime_value': customer.total_spent,
                'days_since_last_order': (datetime.now() - customer.last_order_date).days if customer.last_order_date else None
            }
        }
    
    def register_agent(self, agent: ServiceAgent) -> bool:
        """注册客服代表"""
        try:
            self.agents[agent.agent_id] = agent
            logger.info(f"客服代表 {agent.name} 注册成功")
            return True
        except Exception as e:
            logger.error(f"客服代表注册失败: {e}")
            return False
    
    def assign_ticket_to_agent(self, ticket_id: str, agent_id: str = None) -> bool:
        """分配工单给客服代表"""
        if ticket_id not in self.tickets:
            return False
        
        if agent_id is None:
            # 自动分配给最合适的客服
            agent_id = self._find_best_agent(self.tickets[ticket_id])
        
        if agent_id is None or agent_id not in self.agents:
            return False
        
        agent = self.agents[agent_id]
        if agent.current_tickets >= agent.max_concurrent_tickets:
            logger.warning(f"客服 {agent_id} 工单数量已达上限")
            return False
        
        # 分配工单
        self.tickets[ticket_id].assigned_agent = agent_id
        self.tickets[ticket_id].status = TicketStatus.IN_PROGRESS.value
        self.tickets[ticket_id].updated_date = datetime.now()
        
        # 更新客服状态
        agent.current_tickets += 1
        
        # 记录历史
        self._add_ticket_history(ticket_id, "assigned", f"工单分配给客服 {agent.name}")
        
        logger.info(f"工单 {ticket_id} 分配给客服 {agent.name}")
        return True
    
    def _find_best_agent(self, ticket: ServiceTicket) -> Optional[str]:
        """找到最合适的客服代表"""
        available_agents = [agent for agent in self.agents.values() 
                          if (agent.is_available and 
                              agent.current_tickets < agent.max_concurrent_tickets)]
        
        if not available_agents:
            return None
        
        # 根据技能匹配和工作负载选择最佳客服
        best_agent = None
        best_score = -1
        
        for agent in available_agents:
            score = 0
            
            # 技能匹配分数
            if ticket.category in agent.skills:
                score += 10
            
            # 工作负载分数（负载越低分数越高）
            load_score = (agent.max_concurrent_tickets - agent.current_tickets) / agent.max_concurrent_tickets
            score += load_score * 5
            
            # 客户满意度分数
            score += agent.customer_satisfaction_score
            
            # 优先级加权
            if ticket.priority == TicketPriority.URGENT.value:
                score += 5
            elif ticket.priority == TicketPriority.HIGH.value:
                score += 3
            
            if score > best_score:
                best_score = score
                best_agent = agent
        
        return best_agent.agent_id if best_agent else None
    
    def create_service_ticket(self, ticket_data: Dict) -> Optional[str]:
        """创建服务工单"""
        try:
            ticket_id = f"TKT{datetime.now().strftime('%Y%m%d%H%M%S')}{str(uuid.uuid4())[:6]}"
            
            ticket = ServiceTicket(
                ticket_id=ticket_id,
                customer_id=ticket_data['customer_id'],
                category=ticket_data['category'],
                priority=ticket_data.get('priority', TicketPriority.MEDIUM.value),
                subject=ticket_data['subject'],
                description=ticket_data['description'],
                tags=ticket_data.get('tags', [])
            )
            
            self.tickets[ticket_id] = ticket
            
            # 初始化历史记录
            self._add_ticket_history(ticket_id, "created", "工单创建")
            
            # 自动分配客服（如果有可用的）
            self.assign_ticket_to_agent(ticket_id)
            
            logger.info(f"服务工单 {ticket_id} 创建成功")
            return ticket_id
            
        except Exception as e:
            logger.error(f"创建服务工单失败: {e}")
            return None
    
    def update_ticket_status(self, ticket_id: str, status: str, 
                           resolution: str = "", agent_id: str = "") -> bool:
        """更新工单状态"""
        if ticket_id not in self.tickets:
            return False
        
        ticket = self.tickets[ticket_id]
        old_status = ticket.status
        
        ticket.status = status
        ticket.updated_date = datetime.now()
        
        if resolution:
            ticket.resolution = resolution
        
        if status == TicketStatus.RESOLVED.value:
            ticket.resolved_date = datetime.now()
            
            # 更新客服统计
            if ticket.assigned_agent and ticket.assigned_agent in self.agents:
                agent = self.agents[ticket.assigned_agent]
                agent.current_tickets = max(0, agent.current_tickets - 1)
                agent.total_resolved_tickets += 1
                
                # 更新平均解决时间
                resolution_time = (ticket.resolved_date - ticket.created_date).total_seconds() / 3600
                if agent.total_resolved_tickets == 1:
                    agent.average_resolution_time = resolution_time
                else:
                    agent.average_resolution_time = (
                        (agent.average_resolution_time * (agent.total_resolved_tickets - 1) + resolution_time) /
                        agent.total_resolved_tickets
                    )
        
        elif status == TicketStatus.CLOSED.value and old_status != TicketStatus.CLOSED.value:
            # 释放客服资源
            if ticket.assigned_agent and ticket.assigned_agent in self.agents:
                self.agents[ticket.assigned_agent].current_tickets = max(
                    0, self.agents[ticket.assigned_agent].current_tickets - 1
                )
        
        # 记录历史
        self._add_ticket_history(ticket_id, "status_updated", f"状态从 {old_status} 更新为 {status}")
        
        logger.info(f"工单 {ticket_id} 状态更新为 {status}")
        return True
    
    def _add_ticket_history(self, ticket_id: str, action: str, description: str):
        """添加工单历史记录"""
        if ticket_id not in self.ticket_history:
            self.ticket_history[ticket_id] = []
        
        self.ticket_history[ticket_id].append({
            'timestamp': datetime.now(),
            'action': action,
            'description': description
        })
    
    def create_satisfaction_survey(self, survey_data: Dict) -> Optional[str]:
        """创建满意度调查"""
        try:
            survey_id = f"SUR{datetime.now().strftime('%Y%m%d%H%M%S')}{str(uuid.uuid4())[:6]}"
            
            survey = SatisfactionSurvey(
                survey_id=survey_id,
                customer_id=survey_data['customer_id'],
                ticket_id=survey_data['ticket_id'],
                overall_satisfaction=survey_data['overall_satisfaction'],
                response_time_rating=survey_data['response_time_rating'],
                solution_quality_rating=survey_data['solution_quality_rating'],
                agent_courtesy_rating=survey_data['agent_courtesy_rating'],
                comments=survey_data.get('comments', '')
            )
            
            self.surveys[survey_id] = survey
            
            # 更新工单的满意度评分
            if survey.ticket_id in self.tickets:
                self.tickets[survey.ticket_id].customer_satisfaction = survey.overall_satisfaction
            
            # 更新客服的满意度评分
            if (survey.ticket_id in self.tickets and 
                self.tickets[survey.ticket_id].assigned_agent in self.agents):
                agent_id = self.tickets[survey.ticket_id].assigned_agent
                self._update_agent_satisfaction_score(agent_id)
            
            logger.info(f"满意度调查 {survey_id} 创建成功")
            return survey_id
            
        except Exception as e:
            logger.error(f"创建满意度调查失败: {e}")
            return None
    
    def _update_agent_satisfaction_score(self, agent_id: str):
        """更新客服满意度评分"""
        if agent_id not in self.agents:
            return
        
        # 获取该客服的所有满意度调查
        agent_surveys = []
        for survey in self.surveys.values():
            if (survey.ticket_id in self.tickets and 
                self.tickets[survey.ticket_id].assigned_agent == agent_id):
                agent_surveys.append(survey)
        
        if agent_surveys:
            avg_satisfaction = sum(s.overall_satisfaction for s in agent_surveys) / len(agent_surveys)
            self.agents[agent_id].customer_satisfaction_score = round(avg_satisfaction, 2)
    
    def get_ticket_details(self, ticket_id: str) -> Optional[Dict]:
        """获取工单详细信息"""
        if ticket_id not in self.tickets:
            return None
        
        ticket = self.tickets[ticket_id]
        customer = self.customers.get(ticket.customer_id)
        agent = self.agents.get(ticket.assigned_agent) if ticket.assigned_agent else None
        history = self.ticket_history.get(ticket_id, [])
        
        return {
            'ticket_info': asdict(ticket),
            'customer_info': asdict(customer) if customer else None,
            'assigned_agent': asdict(agent) if agent else None,
            'history': [{
                'timestamp': h['timestamp'].isoformat(),
                'action': h['action'],
                'description': h['description']
            } for h in history]
        }
    
    def get_service_quality_report(self, start_date: datetime = None, 
                                 end_date: datetime = None) -> Dict:
        """获取服务质量分析报告"""
        if start_date is None:
            start_date = datetime.now() - timedelta(days=30)
        if end_date is None:
            end_date = datetime.now()
        
        # 筛选时间范围内的工单
        period_tickets = [ticket for ticket in self.tickets.values() 
                         if start_date <= ticket.created_date <= end_date]
        
        if not period_tickets:
            return {'message': '指定时间范围内无服务数据'}
        
        # 基本统计
        total_tickets = len(period_tickets)
        resolved_tickets = [t for t in period_tickets if t.status == TicketStatus.RESOLVED.value]
        closed_tickets = [t for t in period_tickets if t.status == TicketStatus.CLOSED.value]
        
        # 解决率
        resolution_rate = (len(resolved_tickets) / total_tickets * 100) if total_tickets > 0 else 0
        
        # 平均解决时间
        avg_resolution_time = 0
        if resolved_tickets:
            total_resolution_time = sum(
                (t.resolved_date - t.created_date).total_seconds() / 3600 
                for t in resolved_tickets if t.resolved_date
            )
            avg_resolution_time = total_resolution_time / len(resolved_tickets)
        
        # 优先级分布
        priority_distribution = {}
        for ticket in period_tickets:
            priority = ticket.priority
            priority_distribution[priority] = priority_distribution.get(priority, 0) + 1
        
        # 类别分布
        category_distribution = {}
        for ticket in period_tickets:
            category = ticket.category
            category_distribution[category] = category_distribution.get(category, 0) + 1
        
        # 客服绩效
        agent_performance = {}
        for agent_id, agent in self.agents.items():
            agent_tickets = [t for t in period_tickets if t.assigned_agent == agent_id]
            agent_resolved = [t for t in agent_tickets if t.status == TicketStatus.RESOLVED.value]
            
            agent_performance[agent_id] = {
                'name': agent.name,
                'total_tickets': len(agent_tickets),
                'resolved_tickets': len(agent_resolved),
                'resolution_rate': (len(agent_resolved) / len(agent_tickets) * 100) if agent_tickets else 0,
                'average_resolution_time': agent.average_resolution_time,
                'satisfaction_score': agent.customer_satisfaction_score
            }
        
        # 满意度统计
        period_surveys = [survey for survey in self.surveys.values() 
                         if start_date <= survey.survey_date <= end_date]
        
        satisfaction_stats = {
            'total_surveys': len(period_surveys),
            'average_overall_satisfaction': 0,
            'average_response_time_rating': 0,
            'average_solution_quality_rating': 0,
            'average_agent_courtesy_rating': 0
        }
        
        if period_surveys:
            satisfaction_stats.update({
                'average_overall_satisfaction': round(
                    sum(s.overall_satisfaction for s in period_surveys) / len(period_surveys), 2
                ),
                'average_response_time_rating': round(
                    sum(s.response_time_rating for s in period_surveys) / len(period_surveys), 2
                ),
                'average_solution_quality_rating': round(
                    sum(s.solution_quality_rating for s in period_surveys) / len(period_surveys), 2
                ),
                'average_agent_courtesy_rating': round(
                    sum(s.agent_courtesy_rating for s in period_surveys) / len(period_surveys), 2
                )
            })
        
        return {
            'period': {
                'start_date': start_date.isoformat(),
                'end_date': end_date.isoformat()
            },
            'summary': {
                'total_tickets': total_tickets,
                'resolved_tickets': len(resolved_tickets),
                'closed_tickets': len(closed_tickets),
                'resolution_rate': round(resolution_rate, 2),
                'average_resolution_time_hours': round(avg_resolution_time, 2)
            },
            'distributions': {
                'priority': priority_distribution,
                'category': category_distribution
            },
            'agent_performance': agent_performance,
            'satisfaction_statistics': satisfaction_stats
        }
    
    def export_service_data(self, file_path: str, data_type: str = "tickets") -> bool:
        """导出服务数据"""
        try:
            if data_type == "tickets":
                data = []
                for ticket in self.tickets.values():
                    ticket_data = asdict(ticket)
                    # 转换datetime对象为字符串
                    for key, value in ticket_data.items():
                        if isinstance(value, datetime):
                            ticket_data[key] = value.isoformat()
                    data.append(ticket_data)
            
            elif data_type == "customers":
                data = []
                for customer in self.customers.values():
                    customer_data = asdict(customer)
                    for key, value in customer_data.items():
                        if isinstance(value, datetime):
                            customer_data[key] = value.isoformat()
                    data.append(customer_data)
            
            elif data_type == "surveys":
                data = []
                for survey in self.surveys.values():
                    survey_data = asdict(survey)
                    for key, value in survey_data.items():
                        if isinstance(value, datetime):
                            survey_data[key] = value.isoformat()
                    data.append(survey_data)
            
            else:
                logger.error(f"不支持的数据类型: {data_type}")
                return False
            
            df = pd.DataFrame(data)
            df.to_csv(file_path, index=False, encoding='utf-8-sig')
            logger.info(f"{data_type} 数据已导出到 {file_path}")
            return True
            
        except Exception as e:
            logger.error(f"导出数据失败: {e}")
            return False

# 示例使用
if __name__ == "__main__":
    # 创建客户服务管理系统实例
    csm = CustomerServiceManager()
    
    # 注册客户
    customer = Customer(
        customer_id="CUST001",
        name="张三",
        email="zhangsan@example.com",
        phone="13800138000",
        address="北京市朝阳区",
        registration_date=datetime.now() - timedelta(days=365),
        tier=CustomerTier.GOLD.value,
        total_orders=25,
        total_spent=15000.0,
        last_order_date=datetime.now() - timedelta(days=5)
    )
    csm.register_customer(customer)
    
    # 注册客服代表
    agent = ServiceAgent(
        agent_id="AGT001",
        name="李客服",
        email="likf@company.com",
        department="客户服务部",
        skills=["order_inquiry", "delivery_issue", "general_inquiry"],
        customer_satisfaction_score=4.5
    )
    csm.register_agent(agent)
    
    # 创建服务工单
    ticket_data = {
        'customer_id': 'CUST001',
        'category': TicketCategory.ORDER_INQUIRY.value,
        'priority': TicketPriority.MEDIUM.value,
        'subject': '订单状态查询',
        'description': '客户询问订单ORD12345的配送状态',
        'tags': ['订单查询', '配送']
    }
    
    ticket_id = csm.create_service_ticket(ticket_data)
    if ticket_id:
        print(f"服务工单创建成功: {ticket_id}")
        
        # 更新工单状态
        csm.update_ticket_status(ticket_id, TicketStatus.RESOLVED.value, 
                               "订单正在配送中，预计明天送达")
        
        # 创建满意度调查
        survey_data = {
            'customer_id': 'CUST001',
            'ticket_id': ticket_id,
            'overall_satisfaction': 5,
            'response_time_rating': 4,
            'solution_quality_rating': 5,
            'agent_courtesy_rating': 5,
            'comments': '服务很好，问题解决及时'
        }
        
        survey_id = csm.create_satisfaction_survey(survey_data)
        print(f"满意度调查创建成功: {survey_id}")
        
        # 获取客户360度视图
        customer_view = csm.get_customer_360_view('CUST001')
        print("客户360度视图:", json.dumps(customer_view, indent=2, default=str, ensure_ascii=False))
        
        # 获取服务质量报告
        quality_report = csm.get_service_quality_report()
        print("服务质量报告:", json.dumps(quality_report, indent=2, default=str, ensure_ascii=False))